package com.github.websocket;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.DataFetcher;
import com.github.bean.CallLog;
import com.github.bean.ServerUser;
import com.github.constant.MyConstant;
import com.github.manager.Manager;
import com.github.mq.RedisStreamService;
import com.github.pojo.*;
import com.github.service.CallLogServer;
import com.github.service.UserServer;
import com.github.util.AESEncrypt;
import com.github.util.Role;
import com.github.util.SocketSendThread;
import com.github.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.net.URI;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component("wsHandler")
public class WSHandler extends TextWebSocketHandler {
    // 在控制器或服务中添加测试
    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final ObjectMapper objectMapper = new ObjectMapper();
    //    ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());

    @Autowired
    @Qualifier("userStatusWebSocketHandler")
    private UserStatusWebSocketHandler userStatusWebSocketHandler;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private CallLogServer callLogServer;
    @Autowired
    private RedisStreamService redisStreamService;

    public WSHandler() {
        startHeartbeatChecker();
    }

    private void startHeartbeatChecker() {
        scheduler.scheduleAtFixedRate(() -> {
            try {
                long currentTime = System.currentTimeMillis();
                for (ServerUser user : Manager.accountUserMap.values()) {
                    long lastSHeartbeatTime = user.getLastSHeartbeatTime();
                    long lastCHeartbeatTime = user.getLastCHeartbeatTime();
                    long lastVHeartbeatTime = user.getLastVHeartbeatTime();
//                    logger.info("心跳检测：user-->" + user.getAccount() + ";isServerOnline-->" + user.isServerOnline()
//                            + ";getLastSHeartbeatTime()-->" + lastSHeartbeatTime + ";time-->" + (currentTime - lastSHeartbeatTime) + "\n"
//                            + "                  ;isCardOnline-->" + user.isCardOnline()
//                            + ";getLastCHeartbeatTime()-->" + lastCHeartbeatTime + ";time-->" + (currentTime - lastCHeartbeatTime) + "\n"
//                            + "                  ;isVoiceOnline-->" + user.isVoiceOnline()
//                            + ";getLastVHeartbeatTime()-->" + lastVHeartbeatTime + ";time-->" + (currentTime - lastVHeartbeatTime)
//                    );

                    // 20250420 添加如果拉手在线，语音或插卡离线，超时心跳包给拉手发消息
                    // 若为CALL或VOICE端异常退出，通知SERVER端
                    if (user.isServerOnline()
                            && !user.isCardOnline()
                            && user.getOfflineCNum() < 2
                            && (currentTime - lastCHeartbeatTime) > user.getTimeout() * 1000L) {
                        logger.info("心跳检测：" + user.getAccount() + ";插卡心跳包掉线-->给拉手发消息");
                        user.setOfflineCNum(user.getOfflineCNum() + 1);
                        redisStreamService.sendMessage(user.getServerSessionId(),"1",objectMapper.writeValueAsString(WsResult.deviceOffline(Role.CALL)));
                    }
                    // 若为CALL或VOICE端异常退出，通知SERVER端
                    if (user.isServerOnline()
                            && !user.isVoiceOnline()
                            && user.getOfflineVNum() < 2
                            && (currentTime - lastVHeartbeatTime) > user.getTimeout() * 1000L) {
                        logger.info("心跳检测：" + user.getAccount() + ";语音心跳包掉线-->给拉手发消息");
                        user.setOfflineVNum(user.getOfflineVNum() + 1);
                        redisStreamService.sendMessage(user.getServerSessionId(),"1",objectMapper.writeValueAsString(WsResult.deviceOffline(Role.VOICE)));
                    }


                    if (user.isServerOnline()
                            && lastSHeartbeatTime > 0
                            && (currentTime - lastSHeartbeatTime) > user.getTimeout() * 1000L) {
                        logger.info("心跳超时：拉手:" + user);
                        handleTimeoutUser(user, Role.SERVER);
                    }
                    if (user.isCardOnline()
                            && lastCHeartbeatTime > 0
                            && (currentTime - lastCHeartbeatTime) > user.getTimeout() * 1000L) {
                        logger.info("心跳超时：插卡:" + user);
                        handleTimeoutUser(user, Role.CALL);
                    }
                    if (user.isVoiceOnline()
                            && lastVHeartbeatTime > 0
                            && (currentTime - lastVHeartbeatTime) > user.getTimeout() * 1000L) {
                        logger.info("心跳超时：语音:" + user);
                        handleTimeoutUser(user, Role.VOICE);
                    }

                    //如果都离线了，就全删了
//                    if (!user.isAllOnline()) {
//                        Manager.accountUserMap.remove(user.getAccount());
//                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("心跳检测：异常-->" + e.getMessage());
            }
        }, 1, 1, TimeUnit.SECONDS);
        logger.info("Heartbeat checker started.");
    }

    private void handleTimeoutUser(ServerUser user, int role) {
//        CompletableFuture.runAsync(() -> {
        if (user == null) {
            return;
        }

        try {
            switch (role) {
                case Role.SERVER:
                    if (user.isServerOnline()) {
                        user.getServerSession().close();
                    }
                    user.setLastSHeartbeatTime(0);
                    updateUserStatus(user); // 触发状态更新
                    break;
                case Role.CALL:
                    if (user.isCardOnline()) {
                        user.getCallSession().close();
                    }
                    user.setLastCHeartbeatTime(0);
                    updateUserStatus(user);
                    break;
                case Role.VOICE:
                    if (user.isVoiceOnline()) {
                        user.getVoiceSession().close();
                    }
                    user.setLastVHeartbeatTime(0);
                    updateUserStatus(user);
                    break;
            }
            logger.info("User " + user.getAccount() + " heartbeat timeout, removed.");
        } catch (Exception e) {
            e.printStackTrace();
        }
//        });
    }

    public void updateUserStatus(ServerUser serverUser) throws JsonProcessingException {
//        // 构造用户状态对象
//        UserStatus updatedUser = new UserStatus(
//                serverUser.getAccount(),
//                "更新时不需要密码",
//                serverUser.isServerOnline(),
//                serverUser.isCardOnline(),
//                serverUser.isVoiceOnline()
//        );
//
//        // 获取总用户数和在线用户数
//        long allUsersCount = userServer.getAllUser().size();
//        long onlineUsersCount = getOnlineUser().size();
//
//        // 构造完整的消息对象
//        Map<String, Object> message = new HashMap<>();
//        message.put("username", updatedUser.getUsername());
//        message.put("handshakeConnected", updatedUser.isHandshakeConnected());
//        message.put("cardConnected", updatedUser.isCardConnected());
//        message.put("voiceConnected", updatedUser.isVoiceConnected());
//        message.put("allUsersCount", allUsersCount);       // 总用户数
//        message.put("onlineUsersCount", onlineUsersCount); // 在线用户数
//        // 更新用户状态
//        String jsonMessage = objectMapper.writeValueAsString(message); // 将对象转为 JSON
//        userStatusWebSocketHandler.broadcastUserStatus(jsonMessage);
    }

    // 当有新的WebSocket连接建立时触发
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
//        CompletableFuture.runAsync(() -> {
        try {
            URI uri = session.getUri();
            if (uri == null) {
                //关闭连接
                Utils.delayedCheck(session, 1000);
                return;
            }

            logger.info("新设备连接: session：" + session.getId() + ";uri" + uri);
            String query = uri.getQuery();
            String deviceID = Utils.getParamValue(query, "device_id");
            String device_type = Utils.getParamValue(query, "device_type");
            String account = null;
            String jsonData = "";
            if (device_type.equals("1")) { //拉手
                String token = Utils.getParamValue(query, "token");
                jsonData = objectMapper.writeValueAsString(WsResult.success(1));
                //通过登录接口的token获取账号
                 account =(String) stringRedisTemplate.opsForHash().get(MyConstant.UserLoginToken , token);
                logger.info("Account: " + account);
                //如果没有获取到账号说明没有登陆，添加逻辑让客户退出到登陆界面
                if (account == null || account.isEmpty()) {
                    String msgJson = objectMapper.writeValueAsString(WsBaseResult.kick());
                    redisStreamService.sendMessage(session.getId(),"1",msgJson);
                    Utils.delayedCheck(session, 1000);
                } else {
                    ServerUser serverUser = Manager.accountUserMap.getOrDefault(account, null);
                    if (serverUser == null) {
                        serverUser = new ServerUser(account, deviceID, token, session);
                        serverUser.setLastSHeartbeatTime(System.currentTimeMillis());
                        Manager.accountUserMap.put(account, serverUser);
                    } else {

                        serverUser.setLastSHeartbeatTime(System.currentTimeMillis());
                        serverUser.setServerSession(session);
                        Runnable task = () -> {
                            //Utils.checkDevice(Manager.accountUserMap.getOrDefault(account, null));
                        };
                        scheduler.schedule(task, 1, TimeUnit.SECONDS);
                    }
                    Manager.sessionIDUserMap.put(session.getId(), serverUser);
                    updateUserStatus(serverUser);
                    logger.info("服务端上线 ==> Token " + token);
                }
            } else if (device_type.equals("2") || device_type.equals("3")) { //语音  或  插卡
                 account = Utils.getParamValue(query, "account");
                ServerUser serverUser = Manager.accountUserMap.getOrDefault(account, null);
                if (serverUser != null) {
                    redisStreamService.sendMessage(serverUser.getServerSessionId(),"1",
                            objectMapper.writeValueAsString(WsResult.deviceOnline(Integer.parseInt(device_type))));
                    if (device_type.equals("2")) {
                        serverUser.setLastCHeartbeatTime(System.currentTimeMillis());
                        serverUser.setCallSession(session);
                        logger.info("插卡端上线 ==> Account: " + account);
                    } else {
                        serverUser.setLastVHeartbeatTime(System.currentTimeMillis());
                        serverUser.setVoiceSession(session);
                        logger.info("语音端上线 ==> Account: " + account);
                    }

//                    Manager.deviceIDUserMap.put(deviceID, serverUser);
                    Manager.sessionIDUserMap.put(session.getId(), serverUser);
                    updateUserStatus(serverUser);
                } else {
                    ServerUser user = new ServerUser();
                    user.setAccount(account);
                    if (device_type.equals("2")) {
                        user.setLastCHeartbeatTime(System.currentTimeMillis());
                        user.setCallSession(session);
                        logger.info("插卡端上线 ==> Account: " + account);
                    } else {
                        user.setLastVHeartbeatTime(System.currentTimeMillis());
                        user.setVoiceSession(session);
                        logger.info("语音端上线 ==> Account: " + account);
                    }
                    Manager.accountUserMap.put(account, user);
//                    Manager.deviceIDUserMap.put(deviceID, user);
                    Manager.sessionIDUserMap.put(session.getId(), user);
                    updateUserStatus(user);
                }
                jsonData = objectMapper.writeValueAsString(WsResult.success(4));
            } else {
                logger.info("未知端: " + query);
                //未知端，断开连接
                Utils.delayedCheck(session, 1000);
            }
            logger.info("新设备连接: jsonData" + jsonData);
//            session.sendMessage(new TextMessage(AESEncrypt.encrypt(jsonData)));
            //SocketSendThread.sendMessage(session, jsonData);
            redisStreamService.sendAccountMessage(account,device_type,jsonData);
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("设备上线异常: " + e.getMessage());
        }
//        });
    }

    // 在 WSHandler 类中添加 RateLimiter
//    private RateLimiter rateLimiter = RateLimiter.create(1); // 每秒最多处理 100 个请求

    // 当接收到客户端发送的消息时触发
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
//        CompletableFuture.runAsync(() -> {
        try {
            String msg = AESEncrypt.decrypt(message.getPayload());
            JsonNode rootNode = objectMapper.readTree(msg);
            int msg_type = rootNode.path("msg_type").asInt();
//        if (rateLimiter.tryAcquire()) {
            if (msg_type != 2) {
//                    logger.info("收到消息: session-->" + session + ";msg-->" + msg);
                logger.info("收到消息: msg-->" + msg);
            }
//            String deviceID = rootNode.path("device_id").asText();
            ServerUser serverUser = Manager.sessionIDUserMap.get(session.getId());
            //如果没有获取到serverUser说明没有正确连接，添加逻辑让客户退出到登陆界面
            if (serverUser == null) {
                String json = objectMapper.writeValueAsString(WsBaseResult.kick());
                redisStreamService.sendMessage(session.getId(), String.valueOf(msg_type),json);
                Utils.delayedCheck(session, 1000);
            } else {
                int device_type = -1;
                if (rootNode.has("device_type")) {
                    device_type = rootNode.path("device_type").asInt();
                }
                String jsonString = "";
                switch (msg_type) {
                    case 2: //客户端心跳包
//                        logger.info("心跳包: session-->" + session + ";msg-->" + msg);
                        jsonString = objectMapper.writeValueAsString(WsBaseResult.pong());
                        if (device_type == Role.SERVER) {
                            serverUser.setLastSHeartbeatTime(System.currentTimeMillis()); // 更新心跳时间戳
                        } else if (device_type == Role.CALL) {
                            serverUser.setLastCHeartbeatTime(System.currentTimeMillis()); // 更新心跳时间戳
                        } else if (device_type == Role.VOICE) {
                            serverUser.setLastVHeartbeatTime(System.currentTimeMillis()); // 更新心跳时间戳
                        }
                        break;
                    case 3:
                        JsonNode msgNode = rootNode.path("msg_data");
                        if (device_type == Role.SERVER) {
                            if (msgNode.has("room_id")) {
                                long requestID = rootNode.path("request_id").asLong();
                                String room_id = msgNode.path("room_id").asText();
                                String stream_id = msgNode.path("stream_id").asText();

                                String voiceMsg = objectMapper.writeValueAsString(WsMsgResult.success(new Room(room_id, stream_id, 4)));
                                redisStreamService.sendMessage(session.getId(), "3",voiceMsg);

                                String serverMsg = objectMapper.writeValueAsString(WsDataResult.success(requestID, ResStatus.success(4)));
                                redisStreamService.sendMessage(session.getId(), "1",serverMsg);
                            } else if (msgNode.has("remote_call")) {
                                long requestID = rootNode.path("request_id").asLong();
                                serverUser.setLastRequestStartCallToCard(requestID);
                                String remoteCall = msgNode.path("remote_call").asText();
                                CallLog callLog = new CallLog(requestID, remoteCall, serverUser.getAccount(), System.currentTimeMillis());
                                Runnable task = () -> {
                                    try {
                                        redisStreamService.sendMessage(session.getId(), "2",objectMapper.writeValueAsString(WsMsgResult.success(requestID, new RemoteCall(remoteCall, 1))));
                                    } catch (JsonProcessingException e) {
                                        throw new RuntimeException(e);
                                    }
                                };
                                scheduler.schedule(task, Manager.delay, TimeUnit.SECONDS);
                                // 回复服务端通知成功
                                String serverMsg = objectMapper.writeValueAsString(WsDataResult.success(requestID, ResStatus.success(1)));
                                redisStreamService.sendMessage(session.getId(), "1",serverMsg);
                                callLogServer.addCallLog(callLog);
                            } else if (msgNode.has("hang_up")) {
                                // 接到服务端挂电话
                                long requestID = rootNode.path("request_id").asLong();
                                boolean hangUp = msgNode.path("hang_up").asBoolean();
                                int hangUpType = msgNode.path("hang_up_type").asInt();
                                // 通知插卡端挂断电话
                                String callMsg = objectMapper.writeValueAsString(WsMsgResult.success(new CallStatus(hangUp, hangUpType, 3)));
                                redisStreamService.sendMessage(session.getId(),"2",callMsg);
                                // 回复服务端通知成功
                                String serverMsg = objectMapper.writeValueAsString(WsDataResult.success(requestID, ResStatus.success(3)));
                                redisStreamService.sendMessage(session.getId(),"3",serverMsg);
                                logger.info("收到消息: 拉手挂断电话，通知插卡端挂断电话，回复服务端通知成功");
                                callLogServer.setEndTime(serverUser.getLastRequestStartCallToCard(), System.currentTimeMillis());
                                callLogServer.setMsg(serverUser.getLastRequestStartCallToCard(), "", false);
                            }
                        } else if (device_type == Role.CALL) {
                            if (msgNode.has("telephone_number")) {
                                String telephoneNumber = msgNode.path("telephone_number").asText();
                                redisStreamService.sendMessage(session.getId(), "1",objectMapper.writeValueAsString(WsMsgResult.success(new Telephone(telephoneNumber, 2))));
                            } else if (msgNode.has("hang_up")) {
                                // 接到插卡端，挂电话通知
                                long requestID = rootNode.path("request_id").asLong();
                                boolean hangUp = msgNode.path("hang_up").asBoolean();
                                int hangUpType = msgNode.path("hang_up_type").asInt();
                                // 通知服务端挂断电话
                                String serverMsg = objectMapper.writeValueAsString(WsMsgResult.success(new CallStatus(hangUp, hangUpType, 3)));
                                redisStreamService.sendMessage(session.getId(),"1",serverMsg);

                                // 回复插卡端通知成功
                                String callMsg = objectMapper.writeValueAsString(WsDataResult.success(requestID, ResStatus.success(3)));
                                redisStreamService.sendMessage(session.getId(),"2",callMsg);
                                logger.info("收到消息: 插卡挂断电话，通知服务端挂断电话，回复插卡端通知成功");

                                callLogServer.setEndTime(serverUser.getLastRequestStartCallToCard(), System.currentTimeMillis());
                                callLogServer.setMsg(serverUser.getLastRequestStartCallToCard(), "", false);
                            }
                        } else if (device_type == Role.VOICE) {
                            if (msgNode.has("room_id")) {
                                long requestID = rootNode.path("request_id").asLong();
                                String room_id = msgNode.path("room_id").asText();
                                String stream_id = msgNode.path("stream_id").asText();
                                String serverMsg = objectMapper.writeValueAsString(WsMsgResult.success(new Room(room_id, stream_id, 4)));
                                redisStreamService.sendMessage(session.getId(),"1",serverMsg);
                                String voiceMsg = objectMapper.writeValueAsString(WsDataResult.success(requestID, ResStatus.success(4)));
                                redisStreamService.sendMessage(session.getId(),"3",voiceMsg);
                            }
                        } else {
                            logger.info("未知设备类型: " + device_type);
                            return;
                        }
                        break;
                    case 4:
                        // 插卡或声音端退出信号
                        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

                        WsResult<?> readValue = objectMapper.readValue(msg, WsResult.class);
                        String serverMsg = objectMapper.writeValueAsString(WsResult.deviceOffline(readValue.getDevice_type()));
                        redisStreamService.sendMessage(session.getId(), "1",serverMsg);
                        session.close();
                        break;
                    case 5:
                        // long requestID = rootNode.path("request_id").asLong();
                        // if (device_type == Role.CALL && requestID == serverUser.getLastRequestStartCallToCard()) {
                        //     // scheduler.shutdown();
                        //     // Utils.toServerSendMsg(serverUser, WsDataResult.success(requestID, ResStatus.success(2)));
                        // }
                        jsonString = objectMapper.writeValueAsString(WsBaseResult.pong());
                        break;
                    case 8:
                        String forwardMsg = rootNode.path("forward_msg").path("msg").asText();
                        if (device_type == Role.CALL && forwardMsg.contains("本次呼叫号码被篡改")) {
                            callLogServer.setMsg(serverUser.getLastRequestStartCallToCard(), forwardMsg, true);
                        } else if (device_type == Role.CALL && forwardMsg.contains("插卡端默认拨号应用已被篡改")) {
//                            callLogServer.setMsg(serverUser.getLastRequestStartCallToCard(), forwardMsg, true);
                        } else {
                            String serverMsg1 = objectMapper.writeValueAsString(ForwardMsg.sendMsg(forwardMsg));
                            redisStreamService.sendMessage(session.getId(), "1",serverMsg1);
                        }
                }
                if (!jsonString.isEmpty()) {
                    if (msg_type != 2) {
                        logger.info("回复消息: " + jsonString);
                    }
//                    session.sendMessage(new TextMessage(AESEncrypt.encrypt(jsonString)));
                    redisStreamService.sendMessage(session.getId(), String.valueOf(device_type),jsonString);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("接收数据处理异常: " + e.getMessage());
        }
//        });

//        } else {
//            // 限流处理，例如返回错误消息给客户端
//            session.sendMessage(new TextMessage(AESEncrypt.encrypt(objectMapper.writeValueAsString(WsResult.error(msg_type, "请求过于频繁，请稍后再试")))));
//        }
    }

    // 当WebSocket连接关闭时触发
    @Override
    public void afterConnectionClosed(WebSocketSession session, org.springframework.web.socket.CloseStatus status) throws Exception {
//        CompletableFuture.runAsync(() -> {
        ServerUser serverUser = Manager.sessionIDUserMap.getOrDefault(session.getId(), null);
        if (serverUser == null) {
            logger.info("WebSocket连接已关闭: " + session.getId());
        } else {
//            int deviceType = -1;
//            if (serverUser.getCallSession() != null && session.equals(serverUser.getCallSession())) {
//                deviceType = Role.CALL;
//                serverUser.setLastCHeartbeatTime(0);
//                serverUser.setCallSession(null);
//            } else if (serverUser.getVoiceSession() != null && session.equals(serverUser.getVoiceSession())) {
//                deviceType = Role.VOICE;
//                serverUser.setLastVHeartbeatTime(0);
//                serverUser.setVoiceSession(null);
//            }

//        try {
//            if (serverUser.getServerSession() != null && session.equals(serverUser.getServerSession())) {
//                dataFetcher.delTokenByAccount(serverUser.getAccount());
//                dataFetcher.delAccountByToken(serverUser.getToken());
//            }
//            else if (serverUser.getCallSession() != null && session.equals(serverUser.getCallSession())) {
//                dataFetcher.delTokenByAccount(serverUser.getAccount());
//                dataFetcher.delAccountByToken(serverUser.getToken());
//            } else if (serverUser.getVoiceSession() != null && session.equals(serverUser.getVoiceSession())) {
//                dataFetcher.delTokenByAccount(serverUser.getAccount());
//                dataFetcher.delAccountByToken(serverUser.getToken());
//            }
//        } catch (Exception e) {
//            logger.info("异常1 ==> " + e.getMessage());
//        }

//        try {
//            if (serverUser.getServerSession() != null) { //有拉手信息
//                //掉线的是拉手，
//                if (session.getId().equals(serverUser.getServerSession().getId()) || !serverUser.isServerOnline()) {
//                    dataFetcher.delTokenByAccount(serverUser.getAccount());
//                    dataFetcher.delAccountByToken(serverUser.getToken());
//                }
//            } else {
//                if (!serverUser.isServerOnline()) { //拉手不在线
//                    dataFetcher.delTokenByAccount(serverUser.getAccount());
//                    dataFetcher.delAccountByToken(serverUser.getToken());
//                }
//            }
//        } catch (Exception e) {
//            logger.info("异常2 ==> " + e.getMessage());
//        }

            //20250427 修改逻辑
//        try {
//            if (serverUser.getServerSession() != null) { //有拉手信息
//                //掉线的是拉手
//                if (session.getId().equals(serverUser.getServerSession().getId())) {
//                    dataFetcher.delTokenByAccount(serverUser.getAccount());
//                    dataFetcher.delAccountByToken(serverUser.getToken());
//                }
//            }
//        } catch (Exception e) {
//            logger.info("异常2 ==> " + e.getMessage());
//        }

//            // 若为CALL或VOICE端异常退出，通知SERVER端
//            if (deviceType == Role.CALL || deviceType == Role.VOICE) {
//                Utils.toServerSendMsg(serverUser, WsResult.deviceOffline(deviceType));
//            }

            try {
                updateUserStatus(serverUser);
                logger.info("WebSocket连接已关闭: " + serverUser.getAccount() + "-->" + session.getId());
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("WebSocket连接关闭异常: " + session.getId() + "\ne-->" + e.getMessage());
            }
        }
    }

    private List<ServerUser> getOnlineUser() {
        List<ServerUser> users = Manager.accountUserMap.values().stream()
                .filter(user -> user.isServerOnline() || user.isCardOnline() || user.isVoiceOnline())
                .collect(Collectors.toList());
        return users;
    }
}